home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / hplip / base / tui.py < prev    next >
Text File  |  2009-10-09  |  14KB  |  484 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20. #
  21.  
  22. # Std Lib
  23. import sys
  24. import re
  25.  
  26. # Local
  27. from g import *
  28. import pexpect
  29. import utils
  30.  
  31.  
  32. def enter_yes_no(question, default_value='y', choice_prompt=None):
  33.     if type(default_value) == type(""):
  34.         if default_value == 'y':
  35.             default_value = True
  36.         else:
  37.             default_value = False
  38.  
  39.     #assert default_value in [True, False]
  40.  
  41.     if choice_prompt is None:
  42.         if default_value:
  43.             question += " (y=yes*, n=no, q=quit) ? "
  44.         else:
  45.             question += " (y=yes, n=no*, q=quit) ? "
  46.     else:
  47.         question += choice_prompt
  48.  
  49.     while True:
  50.         try:
  51.             user_input = raw_input(log.bold(question)).lower().strip()
  52.         except EOFError:
  53.             continue
  54.  
  55.         if not user_input:
  56.             return True, default_value
  57.  
  58.         if user_input == 'n':
  59.             return True, False
  60.  
  61.         if user_input == 'y':
  62.             return True, True
  63.  
  64.         if user_input in ('q', 'c'): # q -> quit, c -> cancel
  65.             return False, default_value
  66.  
  67.         log.error("Please press <enter> or enter 'y', 'n', or 'q'.")
  68.  
  69.  
  70. def enter_range(question, min_value, max_value, default_value=None):
  71.     while True:
  72.         try:
  73.             user_input = raw_input(log.bold(question)).lower().strip()
  74.         except EOFError:
  75.             continue
  76.  
  77.         if not user_input:
  78.             if default_value is not None:
  79.                 return True, default_value
  80.  
  81.         if user_input == 'q':
  82.             return False, default_value
  83.  
  84.         try:
  85.             value_int = int(user_input)
  86.         except ValueError:
  87.             log.error('Please enter a number between %d and %d, or "q" to quit.' %
  88.                 (min_value, max_value))
  89.             continue
  90.  
  91.         if value_int < min_value or value_int > max_value:
  92.             log.error('Please enter a number between %d and %d, or "q" to quit.' %
  93.                 (min_value, max_value))
  94.             continue
  95.  
  96.         return True, value_int
  97.  
  98.  
  99. def enter_choice(question, choices, default_value=None):
  100.     if 'q' not in choices:
  101.         choices.append('q')
  102.  
  103.     while True:
  104.         try:
  105.             user_input = raw_input(log.bold(question)).lower().strip()
  106.         except EOFError:
  107.             continue
  108.  
  109.  
  110.         if (not user_input and default_value) or user_input == default_value:
  111.             if default_value == 'q':
  112.                 return False, default_value
  113.             else:
  114.                 return True, default_value
  115.  
  116.         #print user_input
  117.         if user_input == 'q':
  118.             return False, user_input
  119.  
  120.         if user_input in choices:
  121.             return True, user_input
  122.  
  123.         log.error("Please enter %s or press <enter> for the default of '%s'." %
  124.             (', '.join(["'%s'" % x for x in choices]), default_value))
  125.  
  126.  
  127. def title(text):
  128.     log.info("")
  129.     log.info("")
  130.     log.info(log.bold(text))
  131.     log.info(log.bold("-"*len(text)))
  132.  
  133.  
  134. def header(text):
  135.     c = len(text)
  136.     log.info("")
  137.     log.info("-"*(c+4))
  138.     log.info("| "+text+" |")
  139.     log.info("-"*(c+4))
  140.     log.info("")
  141.  
  142.  
  143. def load_paper_prompt():
  144.     return continue_prompt("A page will be printed.\nPlease load plain paper into the printer.")
  145.  
  146.  
  147. def load_scanner_for_align_prompt():
  148.     return continue_prompt("Load the alignment page on the scanner bed and push the 'Scan' or 'Enter' button on the printer to complete the alignment.")
  149.  
  150. def load_photo_paper_prompt():
  151.     return continue_prompt("A page will be printed.\nPlease load HP Advanced Photo Paper - Glossy into the printer.")
  152.  
  153.  
  154. def continue_prompt(prompt=''):
  155.     while True:
  156.         try:
  157.             x = raw_input(log.bold(prompt + " Press <enter> to continue or 'q' to quit: ")).lower().strip()
  158.         except EOFError:
  159.             continue
  160.  
  161.         if not x:
  162.             return True
  163.  
  164.         elif x == 'q':
  165.             return  False
  166.  
  167.         log.error("Please press <enter> or enter 'q' to quit.")
  168.  
  169.  
  170. def enter_regex(regex, prompt, pattern, default_value=None):
  171.     re_obj = re.compile(regex)
  172.     while True:
  173.         try:
  174.             x = raw_input(log.bold(prompt))
  175.         except EOFError:
  176.             continue
  177.  
  178.         if not x and default_value is not None:
  179.             return default_value, x
  180.  
  181.         elif x == 'q':
  182.             return False, default_value
  183.  
  184.         match = re_obj.search(x)
  185.  
  186.         if not match:
  187.             log.error("Incorrect input. Please enter correct input.")
  188.             continue
  189.  
  190.         return True, x
  191.  
  192.  
  193. def ttysize():
  194.     try:
  195.         import commands # TODO: Replace with subprocess (commands is deprecated in Python 3.0)
  196.         ln1 = commands.getoutput('stty -a').splitlines()[0]
  197.         vals = {'rows':None, 'columns':None}
  198.         for ph in ln1.split(';'):
  199.             x = ph.split()
  200.             if len(x) == 2:
  201.                 vals[x[0]] = x[1]
  202.                 vals[x[1]] = x[0]
  203.         return int(vals['rows']), int(vals['columns'])
  204.     except TypeError:
  205.         return 40, 64
  206.  
  207.  
  208. class ProgressMeter(object):
  209.     def __init__(self, prompt="Progress:"):
  210.         self.progress = 0
  211.         self.prompt = prompt
  212.         self.prev_length = 0
  213.         self.spinner = "\|/-\|/-*"
  214.         self.spinner_pos = 0
  215.         self.max_size = ttysize()[1] - len(prompt) - 25
  216.         self.update(0)
  217.  
  218.     def update(self, progress, msg=''): # progress in %
  219.         self.progress = progress
  220.  
  221.         x = self.progress * self.max_size / 100
  222.         if x > self.max_size: x = self.max_size
  223.  
  224.         if self.progress >= 100:
  225.             self.spinner_pos = 8
  226.             self.progress = 100
  227.  
  228.         sys.stdout.write("\b" * self.prev_length)
  229.  
  230.         y = "%s [%s%s%s] %d%%  %s   " % \
  231.             (self.prompt, '*'*(x-1), self.spinner[self.spinner_pos],
  232.              ' '*(self.max_size-x), self.progress, msg)
  233.  
  234.         sys.stdout.write(y)
  235.  
  236.         sys.stdout.flush()
  237.         self.prev_length = len(y)
  238.         self.spinner_pos = (self.spinner_pos + 1) % 8
  239.  
  240.  
  241.  
  242. class Formatter(object):
  243.     def __init__(self, margin=2, header=None, min_widths=None, max_widths=None):
  244.         self.margin = margin # int
  245.         self.header = header # tuple of strings
  246.         self.rows = [] # list of tuples
  247.         self.max_widths = max_widths # tuple of ints
  248.         self.min_widths = min_widths # tuple of ints
  249.  
  250.  
  251.     def add(self, row_data): # tuple of strings
  252.         self.rows.append(row_data)
  253.  
  254.  
  255.     def output(self):
  256.         if self.rows:
  257.             num_cols = len(self.rows[0])
  258.             for r in self.rows:
  259.                 if len(r) != num_cols:
  260.                     log.error("Invalid number of items in row: %s" % r)
  261.                     return
  262.  
  263.             if len(self.header) != num_cols:
  264.                 log.error("Invalid number of items in header.")
  265.  
  266.             min_calc_widths = []
  267.             for c in self.header:
  268.                 header_parts = c.split(' ')
  269.                 max_width = 0
  270.                 for x in header_parts:
  271.                     max_width = max(max_width, len(x))
  272.  
  273.                 min_calc_widths.append(max_width)
  274.  
  275.             max_calc_widths = []
  276.             for x, c in enumerate(self.header):
  277.                 max_width = 0
  278.                 for r in self.rows:
  279.                     max_width = max(max_width, len(r[x]))
  280.  
  281.                 max_calc_widths.append(max_width)
  282.  
  283.             max_screen_width = None
  284.  
  285.             if self.max_widths is None:
  286.                 max_screen_width = ttysize()[1]
  287.                 def_max = 8*(max_screen_width/num_cols)/10
  288.                 self.max_widths = []
  289.                 for c in self.header:
  290.                     self.max_widths.append(def_max)
  291.             else:
  292.                 if len(self.max_widths) != num_cols:
  293.                     log.error("Invalid number of items in max col widths.")
  294.  
  295.             if self.min_widths is None:
  296.                 if max_screen_width is None:
  297.                     max_screen_width = ttysize()[1]
  298.                 def_min = 4*(max_screen_width/num_cols)/10
  299.                 self.min_widths = []
  300.                 for c in self.header:
  301.                     self.min_widths.append(def_min)
  302.             else:
  303.                 if len(self.min_widths) != num_cols:
  304.                     log.error("Invalid number of items in min col widths.")
  305.  
  306.             col_widths = []
  307.             formats = []
  308.             for m1, m2, m3, m4 in zip(self.min_widths, min_calc_widths,
  309.                                       self.max_widths, max_calc_widths):
  310.                 col_width = max(max(m1, m2), min(m3, m4))
  311.                 col_widths.append(col_width)
  312.                 formats.append({'width': col_width, 'margin': self.margin})
  313.  
  314.             formatter = utils.TextFormatter(tuple(formats))
  315.  
  316.             log.info(formatter.compose(self.header))
  317.  
  318.             sep = []
  319.             for c in col_widths:
  320.                 sep.append('-'*c)
  321.  
  322.             log.info(formatter.compose(tuple(sep)))
  323.  
  324.             for r in self.rows:
  325.                 log.info(formatter.compose(r))
  326.  
  327.         else:
  328.             log.error("No data rows")
  329.  
  330.  
  331.  
  332. ALIGN_LEFT = 0
  333. ALIGN_CENTER = 1
  334. ALIGN_RIGHT = 2
  335.  
  336.  
  337. def align(line, width=70, alignment=ALIGN_LEFT):
  338.     space = width - len(line)
  339.  
  340.     if alignment == ALIGN_CENTER:
  341.         return ' '*(space/2) + line + \
  342.                ' '*(space/2 + space%2)
  343.  
  344.     elif alignment == ALIGN_RIGHT:
  345.         return ' '*space + line
  346.  
  347.     else:
  348.         return line + ' '*space
  349.  
  350.  
  351. def format_paragraph(paragraph, width=None, alignment=ALIGN_LEFT):
  352.     if width is None:
  353.         width = ttysize()[1]
  354.  
  355.     result = []
  356.     words = paragraph.split()
  357.     try:
  358.         current, words = words[0], words[1:]
  359.     except IndexError:
  360.         return [paragraph]
  361.  
  362.     for word in words:
  363.         increment = 1 + len(word)
  364.  
  365.         if len(current) + increment > width:
  366.             result.append(align(current, width, alignment))
  367.             current = word
  368.  
  369.         else:
  370.             current = current+" "+word
  371.  
  372.     result.append(align(current, width, alignment))
  373.     return result
  374.  
  375.  
  376. def printer_table(printers):
  377.     header("SELECT PRINTER")
  378.     last_used_printer_name = user_conf.get('last_used', 'printer_name')
  379.     ret = None
  380.  
  381.     table = Formatter(header=('Num', 'CUPS Printer'),
  382.                               max_widths=(8, 100), min_widths=(8, 20))
  383.  
  384.     default_index = None
  385.     for x, _ in enumerate(printers):
  386.         if last_used_printer_name == printers[x]:
  387.             table.add((str(x) + '*', printers[x]))
  388.             default_index = x
  389.         else:
  390.             table.add((str(x), printers[x]))
  391.  
  392.     table.output()
  393.  
  394.     if default_index is not None:
  395.         ok, i = enter_range("\nEnter number 0...%d for printer (q=quit, <enter>=default: *%d) ?" % (x, default_index),
  396.                                 0, x, default_index)
  397.     else:
  398.         ok, i = enter_range("\nEnter number 0...%d for printer (q=quit) ?" % x, 0, x)
  399.  
  400.     if ok:
  401.         ret = printers[i]
  402.  
  403.     return ret
  404.  
  405.  
  406. def device_table(devices, scan_flag=False):
  407.     header("SELECT DEVICE")
  408.     last_used_device_uri = user_conf.get('last_used', 'device_uri')
  409.     ret = None
  410.  
  411.     if scan_flag:
  412.         table = Formatter(header=('Num', 'Scan device URI'),
  413.                                  max_widths=(8, 100), min_widths=(8, 12))
  414.     else:
  415.         table = Formatter(header=('Num', 'Device URI', 'CUPS Printer(s)'),
  416.                                  max_widths=(8, 100, 100), min_widths=(8, 12, 12))
  417.  
  418.     default_index = None
  419.     device_index = {}
  420.     for x, d in enumerate(devices):
  421.         device_index[x] = d
  422.         if last_used_device_uri == d:
  423.             if scan_flag:
  424.                 table.add((str(x) + "*", d))
  425.             else:
  426.                 table.add((str(x) + "*", d, ','.join(devices[d])))
  427.             default_index = x
  428.         else:
  429.             if scan_flag:
  430.                 table.add((str(x), d))
  431.             else:
  432.                 table.add((str(x), d, ','.join(devices[d])))
  433.  
  434.     table.output()
  435.  
  436.     if default_index is not None:
  437.         ok, i = enter_range("\nEnter number 0...%d for device (q=quit, <enter>=default: %d*) ?" % (x, default_index),
  438.                                 0, x, default_index)
  439.     else:
  440.         ok, i = enter_range("\nEnter number 0...%d for device (q=quit) ?" % x, 0, x)
  441.  
  442.     if ok:
  443.         ret = device_index[i]
  444.  
  445.     return ret
  446.  
  447.  
  448. def connection_table():
  449.     ret, ios, x = None, {0: ('usb', "Universal Serial Bus (USB)") }, 1
  450.  
  451.     if prop.net_build:
  452.         ios[x] = ('net', "Network/Ethernet/Wireless (direct connection or JetDirect)")
  453.         x += 1
  454.  
  455.     if prop.par_build:
  456.         ios[x] = ('par', "Parallel Port (LPT:)")
  457.         x += 1
  458.  
  459.     if len(ios) > 1:
  460.         header("SELECT CONNECTION (I/O) TYPE")
  461.  
  462.         table = Formatter(header=('Num', 'Connection Type', 'Description'),
  463.                           max_widths=(8, 20, 80), min_widths=(8, 10, 40))
  464.  
  465.         for x, data in ios.items():
  466.             if x == 0:
  467.                 table.add((str(x) + "*", data[0], data[1]))
  468.             else:
  469.                 table.add((str(x), data[0], data[1]))
  470.  
  471.         table.output()
  472.  
  473.         ok, val = enter_range("\nEnter number 0...%d for connection type (q=quit, enter=usb*) ? " % x,
  474.             0, x, 0)
  475.  
  476.         if ok:
  477.             ret = [ios[val][0]]
  478.  
  479.     else:
  480.         ret = ['usb']
  481.  
  482.     return ret
  483.  
  484.